<template>
  <div>
    <my-breadcrumb :items="['聊天室']"></my-breadcrumb>
    <div>
      <video ref="video" src="../../../assets/notify.mp3" hidden></video>
      <Row>
        <i-col span="6">
          <div class="list"></div>
        </i-col>
        <i-col span="18">
          <div style="margin-bottom: 15px;font-weight: 800;">
            聊天室开关
            <i-switch @on-change="doRegister" v-model="chatSwitch">
              <span slot="open">开</span>
              <span slot="close">关</span>
            </i-switch>
            查看历史消息：<DatePicker type="date" placeholder="选择时间" style="width: 200px" @on-change="timeChange" :readonly="!chatSwitch && openid === ''"></DatePicker>
          </div>
          <div class="detail">
            <div class="top">{{nickname}}</div>
            <div class="mark" ref="mark">聊天室未开启</div>
            <div class="online_list">
              <online-list ref="onlineList" @changeTab="changeTab" @addOnline="addOnline"></online-list>
            </div>
            <div class="content">
              <div class="message" ref="message">
                <div class="load_more" v-if="more && openid !== ''"><Icon type="clock" style="margin-right: 4px;" color="#4c8cfe"></Icon><a href="javascript:void(0)" @click="loadMore">查看更多</a></div>
                <div style="text-align: center;font-size: 12px;color: #333;margin-bottom: 16px;" v-else>已全部加载完成</div>
                <div class="warp" v-for="(message, index) in messageList" :key="index">
                  <div class="time" v-if="index === 0 || message.sendTime - messageList[index - 1].sendTime > 60000">{{message.sendTime | timeFilter}}</div>
                  <div :class="message.sendType === 1 ? 'fl' : 'fr'">
                    <div style="overflow: hidden;">
                      <div :style="{marginLeft: '8px', float: message.sendType === 1 ? 'left' : 'right'}">
                        <Avatar :src="userList[message.senderOpenid].profilePhotoPath" v-if="message.sendType === 1"/>
                        <Avatar v-else/>
                      </div>
                      <div :style="{float: message.sendType === 1 ? 'left' : 'right'}">
                        <div v-if="message.messageType === 1 || message.messageType === 4" class="writing">
                          <div class="arrow"></div>
                          <p v-if="message.messageType === 1">{{message.content}}</p>
                          <p v-if="message.messageType === 4">[公众号图文消息]</p>
                        </div>
                        <div v-if="message.messageType === 2" class="img">
                          <img :src="message.content" alt="图片" width="100" @click="bigImage(message.content)">
                        </div>
                        <div v-if="message.messageType === 3"><voice :media-id="message.content" :a-m-r-recorder="Recorder"></voice></div>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
              <div class="input">
                <div class="progress" v-if="showVioce">
                  <div class="voice_btn">
                    <Button size="small" type="primary" style="height: 20px;" @click="sendVioce">发送</Button>
                    <Button size="small" type="primary" style="height: 20px;" @click="cancel">取消</Button>
                  </div>
                  <Progress :percent="percent" :stroke-width="22">{{count}}s/60s</Progress>
                </div>
                <div class="icon_list">
                  <ul>
                    <li>
                      <Upload
                        ref="upload"
                        action="#"
                        :format="['jpg','jpeg','png']"
                        :max-size="2048"
                        :before-upload="handleBeforeUpload">
                        <Icon type="image"></Icon>
                      </Upload>
                    </li>
                    <li>
                      <Icon type="mic-a" @click="getVoice"></Icon>
                    </li>
                    <li>
                      <Icon type="happy-outline"></Icon>
                    </li>
                    <li>
                      <Icon type="share" @click="shareGoods"></Icon>
                    </li>
                  </ul>
                </div>
                <div class="img_list">
                  <ul>
                    <li v-for="(img, index) in sendImgData" :key="index">
                      <img :src="img" alt="图片" width="50" height="50">
                    </li>
                  </ul>
                </div>
                <div class="text">
                  <textarea v-model="text" style="width: 100%; height: 100%;" @keyup.enter="sendMessage"></textarea>
                </div>
                <div class="btn">
                  <Button type="primary" @click="sendMessage" :disabled="openid === ''">发送</Button>
                </div>
              </div>
            </div>
          </div>
        </i-col>
      </Row>
    </div>
    <transition name="share">
      <div class="goodsShare" v-if="showShare">
        <div class="btn_share">
          <!--<Button type="primary" size="small" @click="sendShare">确定</Button>-->
          <Button type="error" size="small" @click="showShare = false" style="float: right;">取消</Button>
        </div>
        <share-goods ref="share" @sendShare="sendShare"></share-goods>
      </div>
    </transition>
  </div>
</template>

<script>
import onlineList from './onlineList'
import voice from './voice'
import shareGoods from './shareGoods'
const Recorder = require('benz-amr-recorder')
export default {
  name: 'chat',
  data () {
    return {
      Recorder,
      websocket: null,
      messageList: [],
      userList: [],
      text: '',
      oldText: '',
      openid: '',
      nickname: '',
      onlineList: [],
      sendImgData: [],
      sendImgBlob: [],
      type: 0,
      imgId: '',
      showVioce: false,
      percent: 0,
      count: 0,
      vioceInterval: {},
      amr: null,
      showShare: false,
      voiceBlob: null,
      chatSwitch: false,
      more: true
    }
  },
  methods: {
    // 关闭WebSocket连接
    closeWebSocket () {
      this.websocket && this.websocket.close()
    },
    send (openid, messageType, content) {
      let message = JSON.stringify({'receiverOpenid': openid, 'messageType': messageType, 'content': content})
      this.websocket.send(message)
    },
    addMessage (content, type) {
      this.messageList.push({
        sendTime: new Date().getTime(),
        content,
        sendType: 2,
        messageType: type
      })
    },
    openChat (data) {
      // 判断当前浏览器是否支持WebSocket
      if ('WebSocket' in window) {
        this.websocket = new WebSocket('wss://www.gztang.cn/customer/chat/socket/' + data.data.token + '/' + data.data.sessionId)
      } else {
        this.$Notice.error({
          title: '错误',
          desc: '当前浏览器不支持聊天室'
        })
      }

      // 连接发生错误的回调方法
      this.websocket.onerror = () => {
        this.$Notice.error({
          title: '错误',
          desc: 'socket 错误'
        })
      }

      // 连接成功建立的回调方法
      this.websocket.onopen = () => {
        this.$Message.success('成功打开聊天室')
        this.getChatUserList()
        this.$refs.mark.style.display = 'none'
      }

      // 接收到消息的回调方法
      this.websocket.onmessage = (event) => {
        if (event.data === 'true') {
          if (this.type === 1) {
            this.addMessage(this.oldText, 1)
            this.oldText = ''
          } else if (this.type === 2) {
            this.addMessage(this.imgId, 2)
          } else if (this.type === 3) {
            this.addMessage(this.voiceBlob, 3)
          } else if (this.type === 4) {
            this.showShare = false
            this.addMessage('', 4)
          }
          this.$nextTick(() => {
            this.$refs.message.scrollTop = this.$refs.message.scrollHeight
          })
          return
        }
        let data = JSON.parse(event.data)
        if (!this.userList[data.senderOpenid]) {
          this.$refs.onlineList.addOnlineList(data)
          this.userList[data.senderOpenid] = {}
          this.userList[data.senderOpenid].chats = [data]
          return
        }
        this.userList[data.senderOpenid].chats.push(data)
        this.$nextTick(() => {
          this.$refs.message.scrollTop = this.$refs.message.scrollHeight
        })
        this.$refs.onlineList.newMessage(data)
        this.$refs.video.play()
      }

      // 连接关闭的回调方法
      this.websocket.onclose = () => {
        this.$Notice.info({
          title: '通知',
          desc: '聊天室已关闭'
        })
      }
    },
    doRegister (val) {
      if (!val) {
        this.closeWebSocket()
        this.$refs.mark.style.display = 'block'
        this.userList = []
        this.messageList = []
        this.onlineList = []
        this.$refs.onlineList.clear()
        return
      }
      this.$ajax.post('https://www.gztang.cn/admin/customer/register')
        .then(res => {
          if (res.data.success) {
            this.openChat(res.data)
          } else {
            this.$Message.error('请勿重复打开聊天室')
            this.chatSwitch = false
          }
        })
    },
    sendMessage () {
      this.oldText = this.text
      if (this.text === '' && !this.sendImgBlob[0]) {
        this.$Notice.error({
          title: '错误',
          desc: '不能发送空的消息哦'
        })
        return
      }
      if (this.text !== '') {
        this.type = 1
        this.send(this.openid, 1, this.text)
      }
      this.text = ''
      if (this.sendImgBlob[0]) {
        let data = new FormData()
        data.append('type', 2)
        data.append('file', this.sendImgBlob[0])
        this.$ajax.post('https://www.gztang.cn/admin/material/upload', data, {headers: {'Content-Type': 'multipart/form-data'}}).then(res => {
          if (res.data.success) {
            this.type = 2
            this.imgId = 'https://www.gztang.cn/wx/material/' + res.data.data.mediaId
            this.sendImgBlob = []
            this.sendImgData = []
            this.send(this.openid, 2, res.data.data.mediaId)
          }
        })
      }
    },
    changeTab (openid) {
      this.more = true
      this.openid = openid
      this.userList[openid].chats.forEach(item => {
        if (item.messageType === 2 && item.sendType === 2) {
          if (item.content.substring(0, 8) !== 'https://') {
            item.content = 'https://www.gztang.cn/wx/material/' + item.content
          }
        }
      })
      this.messageList = this.userList[openid].chats
      this.nickname = this.userList[openid].nickname
      this.$nextTick(() => {
        this.$refs.message.scrollTop = this.$refs.message.scrollHeight
      })
    },
    addOnline (data) {
      for (let i in data) {
        this.userList[data.openid][i] = data[i]
      }
    },
    handleBeforeUpload (file) {
      // console.log(file)
      let _self = this
      let reader = new FileReader()
      let img = new Image()
      let canvas = document.createElement('canvas')
      let context = canvas.getContext('2d')
      img.onload = function () {
        canvas.width = this.width
        canvas.height = this.height
        context.clearRect(0, 0, this.width, this.height)
        context.drawImage(img, 0, 0, this.width, this.height)
        canvas.toBlob((blob) => {
          _self.sendImgBlob.push(blob)
        }, 'image/jpeg')
      }
      reader.onload = function (e) {
        _self.sendImgData.push(e.target.result)
        img.src = e.target.result
      }
      reader.readAsDataURL(file)
      return false
    },
    getVoice () {
      this.showVioce = true
      let j = 100 / 60
      this.percent = j
      this.vioceInterval = setInterval(() => {
        this.percent += j
        this.count++
        if (this.count >= 60) {
          clearInterval(this.vioceInterval)
        }
      }, 1000)
      this.amr = new Recorder()
      this.amr.initWithRecord().then(() => {
        this.amr.startRecord()
      })
    },
    initVioce () {
      clearInterval(this.vioceInterval)
      this.count = 0
      this.percent = 0
    },
    cancel () {
      this.showVioce = false
      this.initVioce()
      this.amr.finishRecord()
    },
    sendVioce () {
      this.showVioce = false
      this.amr.finishRecord().then(() => {
        this.voiceBlob = this.amr.getBlob()
        let formData = new FormData()
        formData.append('type', 3)
        formData.append('file', this.amr.getBlob())
        this.$ajax.post('https://www.gztang.cn/admin/material/upload', formData, {headers: {'Content-Type': 'multipart/form-data'}}).then(res => {
          if (res.data.success) {
            this.type = 3
            this.send(this.openid, 3, res.data.data.mediaId)
            this.initVioce()
          }
        })
      })
    },
    loadMore () {
      let params = {
        time: this.messageList[0] ? this.messageList[0].sendTime : 1,
        senderOpenid: this.openid
      }
      this.$ajax.post('/admin/history/user/chat/list', JSON.stringify(params)).then(res => {
        if (res.data.success) {
          if (!res.data.data.chats[0]) {
            this.more = false
          }
          res.data.data.chats.forEach(item => {
            if (item.messageType === 2) {
              item.content = 'https://www.gztang.cn/wx/material/' + item.content
            }
          })
          this.messageList.unshift(...res.data.data.chats)
        }
      })
    },
    shareGoods () {
      // this.send(this.openid, 4, JSON.stringify([194, 195, 196, 197]))
      this.showShare = !this.showShare
    },
    sendShare (id) {
      this.send(this.openid, 4, JSON.stringify(id))
      this.type = 4
    },
    bigImage (url) {
      this.$Modal.confirm({
        render (h) {
          return h('img', {
            style: {
              maxWidth: '375px'
            },
            attrs: {
              src: url
            }
          })
        }
      })
    },
    getChatUserList () {
      this.$ajax.get('/admin/today/chat/list').then(res => {
        if (!res.data.data.userList) {
          return
        }
        this.userList = this.historyHandle({userList: res.data.data.userList, chats: res.data.data.chats})
        this.$refs.onlineList.setOnlineList(this.onlineList)
        this.onlineList[0] && this.changeTab(this.onlineList[0].openid)
        this.$nextTick(() => {
          this.$refs.message.scrollTop = this.$refs.message.scrollHeight
        })
      })
    },
    historyHandle (data) {
      let tempArr = []
      let toArr = []
      data.userList && data.userList.forEach(item => {
        toArr.push(JSON.parse(JSON.stringify(item)))
        this.onlineList.push(JSON.parse(JSON.stringify(item)))
        item.chats = []
        tempArr[item.openid] = item
      })
      data.chats && data.chats.forEach(item => {
        if (item.sendType === 1) {
          tempArr[item.senderOpenid] && tempArr[item.senderOpenid].chats.unshift(item)
        } else if (item.sendType === 2) {
          tempArr[item.receiverOpenid].chats.unshift(item)
        }
      })
      console.log(tempArr, toArr)
      if (data.back) {
        this.userList = tempArr
        if (!toArr[0]) {
          this.messageList = []
          this.more = false
          this.openid = ''
        } else {
          this.changeTab(toArr[0].openid)
        }
        this.$refs.onlineList.addHistory(toArr)
      }
      return tempArr
    },
    timeChange (time) {
      if (time === '') {
        return
      }
      this.$ajax.post('/admin/history/chat/list', new Date(time).valueOf()).then(res => {
        if (res.data.success) {
          this.historyHandle({userList: res.data.data.userList, chats: res.data.data.chats, back: true})
        }
      })
    }
  },
  filters: {
    timeFilter: (val) => {
      let data = new Date(parseInt(val))
      let timeY = data.toTimeString().substr(0, 8)
      let timeM = data.toLocaleDateString()
      let nowDate = new Date()
      if (timeM === nowDate.toLocaleDateString()) {
        timeM = '今天'
      }
      return timeM + ' ' + timeY
    }
  },
  components: {
    onlineList,
    voice,
    shareGoods
  },
  created () {
  },
  mounted () {
  },
  beforeDestroy () {
    this.closeWebSocket()
  }
}
</script>

<style scoped>
  .share-enter-active {
    transition: all .3s ease;
  }
  .share-leave-active {
    transition: all .3s cubic-bezier(1.0, 0.5, 0.8, 1.0);
  }
  .share-enter, .share-leave-to{
    transform: translateX(100px);
    opacity: 0;
  }
.list{
  width: 260px;
  height: 700px;
}
  .detail{
    width: 750px;
    height: 550px;
    border: 1px solid #dddee1;
    overflow: hidden;
    position: relative;
    background-color: #f8f8f9;
  }
  .top{
    background: -webkit-linear-gradient(left, #4c8cfe, #25c7fe);
    height: 30px;
    line-height: 30px;
    text-align: center;
    font-weight: 800;
    font-size: 14px;
    color: #fff;
  }
  .mark{
    position: absolute;
    background-color: rgba(0,0,0,0.5);
    text-align: center;
    color: #fff;
    font-size: 24px;
    line-height: 500px;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 100;
  }
  .online_list{
    float: left;
    width: 220px;
    height: 100%;
    box-sizing: border-box;
    border-right: 1px solid #dddee1;
  }
  .content{
    float: left;
    width: 528px;
    height: 100%;
    box-sizing: border-box;
  }
  .message{
    height: 370px;
    overflow-y: auto;
    padding-right: 10px;
    padding-top: 10px;
  }
  .load_more{
    text-align: center;
    margin-bottom: 24px;
  }
  .load_more a:hover{
    text-decoration: underline;
  }
  .warp{
    margin-bottom: 10px;
    overflow: hidden;
  }
  .fl{
    float: left;
  }
  .fl .writing{
    background-color: #19be6b;
  }
  .fr{
    float: right;
    text-align: right;
  }
  .time{
    text-align: center;
  }
  .input{
    height: 150px;
    position: relative;
  }
  .progress{
    width: 100%;
    height: 22px;
    position: absolute;
    top: -22px;
    left: 0;
  }
  .voice_btn{
    position: absolute;
    right: 80px;
    top: 0;
    z-index: 99;
  }
  .icon_list{
    height: 30px;
    box-sizing: border-box;
    border-top: 1px solid #dddee1;
  }
  .icon_list li{
    width: 32px;
    height: 28px;
    overflow: hidden;
    text-align: center;
    float: left;
    padding: 0 6px;
    box-sizing: padding-box;
    font-size: 18px;
    color: #80848f;
  }
  .icon_list li:hover{
    background-color: #dddee1;
  }
  .img_list{
    overflow: hidden;
    margin-left: 10px;
  }
  .img_list li{
    float: left;
    width: 50px;
    height: 50px;
  }
  .text{
    position: relative;
    padding: 0 10px;
    height: 100px;
    font-size: 14px;
  }
  .text textarea{
    resize: none;
    outline: none;
    border: none;
    background-color: #f8f8f9;
  }
  .btn{
    position: absolute;
    bottom: 15px;
    right: 15px;
  }
  .writing{
    max-width: 350px;
    line-height: 30px;
    background-color: #2d8cf0;
    margin-bottom: 6px;
    margin-left: 10px;
    margin-right: 10px;
    padding: 2px 7px ;
    border-radius: 5px;
    color: #000;
    position: relative;
  }
  .writing p{
    word-break: break-all;
    word-wrap: break-word;
    white-space: pre-wrap;
    color: #fff;
  }
  .img{
    margin-left: 5px;
    border-radius: 5px;
    border: 1px solid #dddee1;
    overflow: hidden;
  }
  .img img{
    display: block;
  }
  .arrow{
    position: absolute;
    width: 8px;
    height: 8px;
    box-sizing: border-box;
    border-top: 4px solid #fff;
    border-bottom: 4px solid #fff;
    top: 13px;
  }
  .fl .arrow{
    left: -8px;
    border-right: 4px solid #19be6b;
  }
  .fr .arrow{
    border-left: 4px solid #2d8cf0;
    right: -8px;
  }
  .goodsShare{
    position: fixed;
    width: 280px;
    top: 0;
    bottom: 0;
    right: 0;
    z-index: 999;
    background-color: #fff;
    border-left: 1px solid #dddee1;
    overflow: auto;
  }
  .btn_share{
    width: 280px;
    position: fixed;
    top: 8px;
    right: 0;
    padding-left: 10px;
    padding-right: 10px;
  }
</style>
